﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using System.IO;
using System.Reflection;
using System.Collections;
#if !Portable
using System.Runtime.Serialization.Formatters.Binary;
#endif
namespace XYZShell.Helper
{

	public class TemplateXmlSerializer
	{
		//public bool test()
		//{
		//	XmlSerializer xs=new XmlSerializer();
		//	xs.Serialize
		//}
		//public void Serialize();
	}

	public class Template
	{
		public Template()
		{
			Key = "";
			Value = "";
			Split = "";
			SubTemplates = new TemplateCollection();
		}
		public Template( string key )
			: this()
		{
			Key = key;
		}
		public Template( string key, string value )
			: this( key )
		{
			Value = value;
		}
		public Template( string key, string value, string split )
			: this( key, value )
		{
			Split = split;
		}
		
		public void Save( string fileName )
		{
			FileStream fs =new FileStream(fileName,FileMode.Create,FileAccess.Write,FileShare.ReadWrite);
			XmlSerializer x=new XmlSerializer( typeof( Template ) );
			x.Serialize( fs, this );
		}

		public static Template Load( string fileName )
		{
			FileStream fs =new FileStream( fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite );
			XmlSerializer x=new XmlSerializer( typeof( Template ) );
			return x.Deserialize( fs ) as Template;
		}

		public Template this[string key]
		{
			get
			{
				return SubTemplates[key];
			}
			//set
			//{
			//	if (SubTemplates[key] != null)
			//		SubTemplates[key] = value;
			//}
		}

		public string Key
		{
			get;
			set;
		}
		public string Value
		{
			get;
			set;
		}
		public string Split
		{
			get;
			set;
		}
		public TemplateCollection SubTemplates
		{
			get;
			set;
		}

	}
	public class TemplateCollection : Collection<Template>
	{
		public Template this[string key]
		{
			get
			{
				return Items.First( ( t ) =>
				{
					return t.Key == key;
				} );
			
			}

		}
	}

	public static class ObjectHelper
	{
		public static string ExportByTemplate( this object o, Template t )
		{
			string rtn=t.Value;
			Type type=o.GetType();
			
			string memStr=@"\{\$(?<mb>\w+)(:(?<k>\w+))*\}";
			Regex rgxMember=new Regex( memStr );

			if (rgxMember.IsMatch( rtn ))
			{
				MatchCollection ms=rgxMember.Matches( t.Value );
				foreach (Match m in ms)
				{
					string mbName=m.Result("${mb}");
					if(mbName=="${mb}") continue;

					FieldInfo fi=null;
					object val=null;
					var pi= type.GetProperty( mbName );
					if (pi == null)
					{
						fi = type.GetField( mbName );
						if (fi == null)
							continue;
						val = fi.GetValue( o );
					}
					else
					{
						val = pi.GetValue( o, null );
					}
					if (val is IEnumerable && !(val is string))
					{
						string enumVal="";
						string mbKey=m.Result( "${k}" );
						if (mbKey == "${k}"||mbKey=="")
							continue;
						foreach (var i in (IEnumerable)val)
						{
							Template tsub= t.SubTemplates[mbKey];
							enumVal +=i.ExportByTemplate(tsub )+tsub.Split;
						}
						rtn=rtn.Replace( m.Value, enumVal );

					}
					else
					{
						rtn = rtn.Replace( m.Value, val.ToString() );
					}
				}
			}

			return rtn;
		}

		/// <summary>
		/// 使用BinaryFormatter序列化对象
		/// </summary>
		/// <param name="o"></param>
		/// <returns></returns>
		public static byte[] SerialToBytes(this object o)
		{
			BinaryFormatter bf = new BinaryFormatter();
			MemoryStream ms=new MemoryStream();
			bf.Serialize( ms, o );
			return ms.ToArray();
		}


	}
}
